import java.util.*;

/**
 * 作业: 自己实现 java.lang.Collection 接口中除了 iterator 和  toArray(T[] a) 之外的其它方法
 */
public class Container implements Collection<Object> {
    private static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;
    private static final int MAXIMUM_CAPACITY = 1 << 30;
    private static final float DEFAULT_LOAD_FACTOR = 0.75f;
    private static final Object UNUSED = new Object();
    private Object[] elements;
    private int counter;
    private float loadFactor;
    public Container() {
        this( DEFAULT_INITIAL_CAPACITY , DEFAULT_LOAD_FACTOR );
    }

    public Container( int initialCapacity ) {
        this( initialCapacity , DEFAULT_LOAD_FACTOR );
    }

    public Container( int initialCapacity, float loadFactor ) {
        // 注意这里的 initialCapacity 的取值范围是 [ 0 , MAXIMUM_CAPACITY ]
        if (initialCapacity < 0 || initialCapacity > MAXIMUM_CAPACITY ) {
            // 创建异常实例 ( 创建 RuntimeException 实例 )
            RuntimeException ex = new RuntimeException("初始容量必须是 [ 0 , " + MAXIMUM_CAPACITY + " ] 之间的正整数值");
            throw ex; // 抛出异常实例，导致当前方法立即结束
        }

        if (loadFactor <= 0 || loadFactor >= 1) {
            // 创建异常实例 ( 创建 RuntimeException 实例 )
            RuntimeException ex = new RuntimeException("加载因子必须是 ( 0 , 1 ) 之间的浮点数");
            throw ex; // 抛出异常实例，导致当前方法立即结束
        }

        // 如果前面两个 if 语句块都未进去执行，则会执行后续操作
        this.elements = new Object[initialCapacity]; // 使用默认初始容量创建数组实例
        this.loadFactor = loadFactor; // 保存用户指定的 加载因子
        this.mark(); // 将整个数组中的所有位置都标记为 UNUSED
    }
    private void mark() {
        // 将整个 elements 数组 填充为 UNUSED
        Arrays.fill( elements ,  UNUSED );
    }
    private void ensureCapacity() {
        // 当达到某个条件时，就对容器进行扩容
        if ( counter > elements.length * loadFactor) {
            // 将 原来的数组 的地址 暂存到 temp 变量中
            final Object[] temp = this.elements;
            // 扩容方式就是在原来基础上增长约 1.5 倍
            int newLength = temp.length * 3 / 2 + 1 ;
            if( newLength > MAXIMUM_CAPACITY ) {
                RuntimeException x = new RuntimeException( "容器容量超过最大值" );
                throw x ; // 抛出异常实例导致整个方法立即结束
            }
            // 创建新数组 ( 创建一个新的、更大的数组 ) 并将新数组地址赋值到 elements 变量
            this.elements = new Object[ newLength ];
            // 将原数组中的[ 0 , counter ) 之间的元素拷贝到新数组中
            System.arraycopy(temp, 0, elements, 0, counter);
            // 后续就使用新数组 (放弃老数组) 了 ( 因为 elements 变量中存储了 新数组的地址 )
        }
    }
    public int indexOf( Object o ) {
        for( int i = 0 ; i < counter ; i++ ) {
            // 从数组中获取下标i处的元素
            Object e = elements[ i ];
            if( e == o || ( e != null && e.equals( o ) ) ) {
                return i ;  // 当找到指定元素时就返回相应的索引
            }
        }
        return -1 ; // 如果未找到相应的元素则返回 -1
    }
    @Override
    public int size() {
        return counter;
    }

    @Override
    public boolean isEmpty() {
        return counter == 0;
    }

    @Override
    public boolean contains(Object o) {
        return this.indexOf( o ) != -1;
    }

    @Override
    public Object[] toArray() {
        Object[] array = Arrays.copyOf( elements ,  counter );
        return array ;
    }

    @Override
    public boolean add(Object e) {
        this.ensureCapacity();

        // 将 element 添加到 elements 数组的 counter 处
        elements[counter] = e;
        // 对 counter 执行 自增操作 ( 增加 1 )
        counter++; // 自增之后的值既表示元素个数又表示下次添加元素时的存放位置

        return true;
    }

    @Override
    public boolean remove(Object o) {
        int index = this.indexOf( o );
        if( index != -1 ) {
            // 统计需要拷贝的元素个数
            int n = counter - 1 - index ;
            // 将 elements 的 [ index + 1 , counter ) 之间的元素 拷贝 到 elements 的 [ index , counter - 1 ) 之间
            System.arraycopy( elements, index + 1 ,  elements , index , n );//【注意这行代码】
            // 将 原本的 counter - 1 处的元素 重置为 UNUSED
            elements[ counter - 1 ] = UNUSED ;
            // 因为删除了一个元素，所以 counter 需要减去 1
            counter-- ;
            return true ;// 成功删除后返回 true
        }
        return false ; // 如果未对容器造成任何影响则返回 false
    }

    @Override
    public void clear() {
        this.counter = 0;
        this.mark();
    }

    @Override
    public boolean containsAll(Collection<?> c) {

        int a = 0;
        for (Object o : c) {
            if (this.indexOf( o ) != -1){
                a++;
            }
        }
        return c.size() == a;
    }

    @Override
    public boolean addAll(Collection<? extends Object> c) {
        for (Object o : c) {
            add(o);
        }
        return false;
    }

    @Override
    public boolean removeAll(Collection<?> c) {

        for (Object o : c) {
            remove(o);
        }
        return  true;
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        for (int i = 0; i < counter; i++) {
            if (c.contains(elements[i]) == false) {
                remove(elements[i]);
                i--;
            }
        }
       /* Iterator it =c.iterator();//获取迭代器，用于取出集合中的元素。

        while(it.hasNext())
        {
           if(this.indexOf(c)==-1)
           {
               remove(c);
           }
        }*/



        return true;
    }

    @Override
    public Iterator<Object> iterator() { // 【不去实现】
        return null;
    }

    @Override
    public <T> T[] toArray(T[] a) { // 【不去实现】
        return null;
    }
    private final StringBuilder builder = new StringBuilder();

    @Override
    public String toString() {
        builder.append( "[" );
        if (counter > 0) {
            for (int i = 0; i < counter; i++) {
                // 将每个元素的字符串形式追加到 builder 末尾
                builder.append( elements[i] );
                builder.append( i < counter - 1 ? "," : "" );
            }
        }
        builder.append( "]" );
        String s = builder.toString();
        // 将 builder 的 length 设置为 零 是为了下次使用 builder 时，从缓冲区的 第一个位置开始存放字符
        builder.setLength( 0 ); // 功能上类似于容器的 clear 方法
        return s;
    }


}
